//
// Created by xkj on 2020/8/11.
//

#ifndef PROJ_ANDROID_HANDWRITESCENE_H
#define PROJ_ANDROID_HANDWRITESCENE_H
#include <stdlib.h>
#include <strings.h>

#include <map>
#include <string>
#include <atomic>

#include <functional>
#include <android/log.h>

#include "base/CCScheduler.h"

#include "HelloWorldScene.h"
#include "base/CCDirector.h"

#include "renderer/CCRenderer.h"
#include "renderer/CCCustomCommand.h"
#include "TianHelper.h"

#include "BlueToothHelper.h"
#include "RemoteControlHelper.h"
#include "../cocos2d/cocos/editor-support/cocostudio/SimpleAudioEngine.h"

using namespace CocosDenshion;

USING_NS_CC;
USING_NS_CC_EXT;

class  HandWriteScene: public cocos2d::Scene,public BlueToothHelperDelegate
{
public:
    static cocos2d::Scene* createScene(){
        return HandWriteScene::create();
    }

    virtual bool init() override {
        if (!Scene::init()) {
            return false;
        }

        penHover = Sprite::create("penhover.png");
        penHover->setScale(1.0);
        penHoverMS = MotionStreak::create(0.5f, 50, 30, Color3B::BLUE, "streak.png");
        //penHover->setColor(Color3B::ORANGE);
        //penHover->setOpacity(30);

        this->addChild(penHover);
        this->addChild(penHoverMS);
        visibleSize = Director::getInstance()->getVisibleSize();

//        SocketIOHelper::delegate =  static_cast<SocketIOHelperDelegate *>(this);

        lineWidth = 4;

        penColor = Color4F::WHITE;

        initAudio();
        initDrawPos();
        initKeyBoard();
        return true;
    }

    void initAudio(){
        SimpleAudioEngine::getInstance()->playBackgroundMusic("pencil.mp3", true);
        SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
        volumn = 1.0;
    }

    void initDrawPos(){
        lastX = -1;
        lastY = -1;
        lastLastX = -1;
        lastLastY = -1;
        curX = -1;
        curX = -1;
    }

    void menuCloseCallback(cocos2d::Ref* pSender)
    {
        auto scene = HelloWorld::createScene();
        Director::getInstance()->replaceScene(TransitionFade::create(2.5, scene, Color3B(58,81,73)));
    }
    cocos2d::Node*        _root;
    cocos2d::Node*        _target;
    cocos2d::MotionStreak* _streak;

    void xxoo() {
        auto s = Director::getInstance()->getWinSize();
        const char s_pathR1[]             = "r1.png";
        const char s_streak[]              = "streak.png";

        // the root object just rotates around
        _root = Sprite::create(s_pathR1);
        addChild(_root, 1);
        _root->setPosition(Vec2(s.width/2, s.height/2));

        // the target object is offset from root, and the streak is moved to follow it
        _target = Sprite::create(s_pathR1);
        _root->addChild(_target);
        _target->setPosition(Vec2(s.width/4, 0.0f));


        // schedule an update on each frame so we can synchronize the streak with the target
        schedule(CC_SCHEDULE_SELECTOR(HandWriteScene::onUpdate));

        auto a1 = RotateBy::create(2, 360);

        auto action1 = RepeatForever::create(a1);
        auto motion = MoveBy::create(2, Vec2(100,0) );
        _root->runAction( RepeatForever::create(Sequence::create(motion, motion->reverse(), nullptr) ) );
        _root->runAction( action1 );


    }

    void onUpdate(float delta)
    {
        //_streak->setPosition( _target->convertToWorldSpace(Vec2::ZERO) );
    }

    void initStreak()
    {
        const char s_streak[]              = "streak.png";

        // create the streak object and add it to the scene
        _streak = MotionStreak::create(0.5, 3, lineWidth*2, Color3B::GREEN, s_streak);
        //addChild(_streak);
        auto colorAction = RepeatForever::create(Sequence::create(
                TintTo::create(0.2f, 255, 0, 0),
                TintTo::create(0.2f, 0, 255, 0),
                TintTo::create(0.2f, 0, 0, 255),
                TintTo::create(0.2f, 0, 255, 255),
                TintTo::create(0.2f, 255, 255, 0),
                TintTo::create(0.2f, 255, 0, 255),
                TintTo::create(0.2f, 255, 255, 255),
                nullptr));

        _streak->runAction(colorAction);
        this->addChild(_streak);
    }

    void initParticle()
    {
        _emitter = ParticleSystemQuad::create("debian.plist");
        _emitter->retain();
        addChild(_emitter, 10);
    }

    virtual void onEnterTransitionDidFinish() override{
        initBg();
        initStreak();
        initParticle();
        Vec2 origin = Director::getInstance()->getVisibleOrigin();

        /////////////////////////////
        // 2. add a menu item with "X" image, which is clicked to quit the program
        //    you may modify it.

        // add a "close" icon to exit the progress. it's an autorelease object
        auto closeItem = MenuItemImage::create(
                "backNormal.png",
                "backSelected.png",
                CC_CALLBACK_1(HandWriteScene::menuCloseCallback, this));

        if (closeItem == nullptr ||
            closeItem->getContentSize().width <= 0 ||
            closeItem->getContentSize().height <= 0)
        {
            Director::getInstance()->popScene();
        }
        else
        {
            float x = origin.x + visibleSize.width - closeItem->getContentSize().width/2;
            float y = origin.y + closeItem->getContentSize().height/2;
            closeItem->setPosition(Vec2(x,y));
        }

        // create menu, it's an autorelease object
        auto menu = Menu::create(closeItem, NULL);
        menu->setPosition(Vec2::ZERO);
        this->addChild(menu);

        /////////////////////////////
        // 3. add your codes below...
        auto item4 = MenuItemFont::create("自由书写", [&](Ref *sender) {
        });

        item4->setFontSizeObj(64);
        item4->setFontName("fonts/content.ttf");
        item4->setName("bandTitle");

        float menuTx = origin.x + visibleSize.width/2;// - closeItem->getContentSize().width/2;
        float menuTyA = origin.y + visibleSize.height/2;//-(item4->getContentSize().height/2);
        float menuTyB = origin.y + visibleSize.height-(item4->getContentSize().height/2);


        displayLabel = Label::createWithTTF("黑板", "fonts/content.ttf", 32);
        auto pMenu = MenuItemLabel::create(displayLabel, [&](Ref *sender) {});
        pMenu->setAnchorPoint(Vec2(0,1));
        pMenu->setPosition(Vec2(5,0));

        // add the label as a child to this layer
        //this->addChild(displayLabel, 2);
        auto menuTop = Menu::create(item4, pMenu,  nullptr);
        menuTop->alignItemsHorizontally();
        menuTop->setPosition(Vec2(menuTx,menuTyA));
        menuTop->setName("menuTop");

        this->addChild(menuTop);

        menuTop->runAction(
                EaseIn::create(MoveTo::create(0.7, Vec2(menuTx,menuTyB)), 1)
        );


        BlueToothHelper::notifyTarget = static_cast<BlueToothHelperDelegate*>(this);

        initDrawThing();
    }

    void checkoutGlobal()
    {
        SocketIOHelper::delegate =  static_cast<SocketIOHelperDelegate *>(nullptr);
        BlueToothHelper::notifyTarget = static_cast<BlueToothHelperDelegate *>(nullptr);
    }

    void initDrawThing()
    {
        handNode = DrawNode::create();
        this->addChild(handNode);
        handNode->setLineWidth(lineWidth);
        handNode->setName("drawer");

        testHandNode = DrawNode::create();
        this->addChild(testHandNode);
        testHandNode->setLineWidth(lineWidth);
        initDrawPos();
    }

    void initDrawTest(float dt) {
        testHandNode->drawQuadBezier(Vec2(793.1428, 463.99), Vec2(1059.56, 393.727), Vec2(139.519, 50.3), 3, Color4F::RED);
        handNode->drawQuadBezier(Vec2(793.1428, 463.99), Vec2(1059.56, 393.727), Vec2(139.519, 50.3), 3, Color4F::RED);
    }

    void resetHandWrite(){
        unsigned  int xx = 1;
        while(true){
            auto oneDrawNode = this->getChildByName("drawer");

            if(oneDrawNode == nullptr){
                break;
            }

            oneDrawNode->removeFromParentAndCleanup(true);

            auto promptStr = StringUtils::format("清除节点%d",xx);
            BlueToothHelper::notifyTarget->setNotifyLabel(promptStr);

            xx++;
        }

        Director::getInstance()->getScheduler()->performFunctionInCocosThread( std::bind(&HandWriteScene::initDrawThing, this) );
    }

    void initKeyBoard(){
        auto listener = EventListenerKeyboard::create();
        listener->onKeyPressed = [=](EventKeyboard::KeyCode keyCode, Event* event){
            ControlCode pressKey = ControlCode(keyCode);
            setKeyAct(pressKey);
//        auto promptxx = StringUtils::format("按下键盘：%d", static_cast<int>(keyCode));
//        BlueToothHelper::notifyTarget->setNotifyLabel(promptxx);
        };

        listener->onKeyReleased = [=](EventKeyboard::KeyCode keyCode, Event* event){
//        auto promptxx = StringUtils::format("抬起键盘：%d", static_cast<int>(keyCode));
//        BlueToothHelper::notifyTarget->setNotifyLabel(promptxx);
        };

        _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
    }

    void setKeyAct(ControlCode &pressKey) override {

        //如果按返回就退出
        if(pressKey == KEY_RETURN) {
            BlueToothHelper::notifyTarget->setNotifyLabel("ヾ(￣▽￣)Bye~Bye~");
            //Director::getInstance()->end()
            checkoutGlobal();
            auto scene = HelloWorld::createScene();

            Director::getInstance()->replaceScene(TransitionFade::create(2.5, scene, Color3B(58,81,73)));
        }

        if(pressKey == VOLUMN_UP ||
           pressKey == VOLUMN_DOWN
        ) {
            if(pressKey == VOLUMN_UP)
            {
                volumn -= 0.1;
                if(volumn<0){
                    volumn = 0;
                    BlueToothHelper::notifyTarget->setNotifyLabel("静音");
                }else{
                    BlueToothHelper::notifyTarget->setNotifyLabel("减小声音");
                }
            }

            if(pressKey == VOLUMN_DOWN){
                volumn += 0.1;
                if(volumn > 1){
                    volumn = 1.0;
                    BlueToothHelper::notifyTarget->setNotifyLabel("最大声音");
                }else{
                    BlueToothHelper::notifyTarget->setNotifyLabel("增大声音");
                }
            }

            SimpleAudioEngine::getInstance()->setBackgroundMusicVolume(volumn);
        }

        if(pressKey == PROGRAM_UP ||
           pressKey == PROGRAM_DONW
        ) {
            if(pressKey == PROGRAM_UP) {
                lineWidth--;
                if(lineWidth < 1){
                    lineWidth = 1;
                }
            }

            if(pressKey == PROGRAM_DONW) {
                lineWidth++;
            }

            Director::getInstance()->getScheduler()->performFunctionInCocosThread( std::bind(&HandWriteScene::initDrawThing, this) );

            auto xx = StringUtils::format("字体粗细:%d",lineWidth);
            BlueToothHelper::notifyTarget->setNotifyLabel(xx);
        }

        if(pressKey == VOLUMN_MUTE){
            Director::getInstance()->getScheduler()->performFunctionInCocosThread( std::bind(&HandWriteScene::resetHandWrite, this) );
            BlueToothHelper::notifyTarget->setNotifyLabel("擦除黑板");
        }

    }

    virtual void setNotifyLabel(std::string cnt) override
    {
        if(displayLabel != nullptr) {
            displayLabel->setString(cnt);
        }
    }

    void hoverPen(ActCmd &oneCmd){
        penHover->setPosition(visibleSize.width*oneCmd.x, visibleSize.height*oneCmd.y);

        //penHoverMS->setPosition( penHover->getPosition() );
        _streak->setPosition(Vec2(visibleSize.width*oneCmd.x, visibleSize.height*oneCmd.y));
        _emitter->getParticleCount();
    }



    void drawHandWrite(ActCmd oneCmd)
    {
        curX = visibleSize.width*oneCmd.x;
        curY = visibleSize.height*oneCmd.y;

        if(lastX >= 0 &&
           lastY >= 0 &&
           lastLastX >= 0 &&
           lastLastY >= 0
        ){
            _emitter->setPosition(Vec2(curX,curY));

            //penHoverMS->setPosition( curX,curY);
            auto onelineWidth = lineWidth * oneCmd.presure;
            handNode->setLineWidth(onelineWidth);

            handNode->drawQuadBezier(Vec2(lastLastX, lastLastY), Vec2(lastX, lastY), Vec2(curX, curY), 30, penColor);
            //handNode->drawDot( Vec2(lastLastX, lastLastY), onelineWidth, penColor);
            //handNode->drawDot( Vec2(lastX, lastY), onelineWidth, penColor);
            //handNode->drawDot( Vec2(curX, curY), onelineWidth, penColor);

            handNode->drawLine(Vec2(lastLastX, lastLastY), Vec2(lastX, lastY), penColor);
            //handNode->drawLine(Vec2(lastLastX, lastLastY), Vec2(lastX, lastY), penColor);
            //handNode->drawLine(Vec2(lastX, lastY), Vec2(curX, curY), penColor);
        }

        lastLastX = lastX;
        lastLastY = lastY;

        lastX = curX;
        lastY = curY;

    }

    //放下一个命令
    virtual void setOneAct(ActCmd &oneCmd) override
    {
        std::string cmd;
        if(oneCmd.act == Pen_Write){
            //坐标转换
            //oneCmd.y = 1-oneCmd.y;
            oneCmd.y = 1-oneCmd.y;
            oneCmd.x = 1-oneCmd.x;

            std::swap(oneCmd.x,oneCmd.y);

            cmd = "得到一个写命令,";

            if(oneCmd.actDetail == PenStatus_Down){
                //penHover->setVisible(false);
                SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
                initDrawPos();
                _streak->reset();
                _streak->setPosition(visibleSize.width*oneCmd.x,visibleSize.height*oneCmd.y);
                cmd.append(",按下,x=");
            }

            if(oneCmd.actDetail == PenStatus_Move){
                Director::getInstance()->getScheduler()->performFunctionInCocosThread( std::bind(&HandWriteScene::drawHandWrite, this, oneCmd) );
                cmd.append(",行走,x=");
            }
            if(oneCmd.actDetail == PenStatus_Up){
                SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
                //penHover->setVisible(true);
                cmd.append(",抬起,x=");

            }

            if(oneCmd.actDetail == PenStatus_Leave){
                penHover->setVisible(false);

                cmd.append(",离开,x=");
            }

            if(oneCmd.actDetail == PenStatus_Hover){
                penHover->setVisible(true);

                cmd.append(",悬浮,x=");
            }

            if(
               oneCmd.actDetail == PenStatus_Move ||
               oneCmd.actDetail == PenStatus_Hover
            )
            {
                hoverPen(oneCmd);
            }
            //cmd.append(std::to_string(oneCmd.x)).append(",y=").append(std::to_string(oneCmd.y)).append(",presure=").append(std::to_string(oneCmd.presure));
            //putNotifyLabel(cmd);
        }

        if(oneCmd.act == Pen_Ctl){
            std::string cmd = "得到一个控制命令-";
            if(oneCmd.actDetail == PenStatus_SAVE){
                cmd.append("保存");
            }
            if(oneCmd.actDetail == PenStatus_CLEAR){
                Director::getInstance()->getScheduler()->performFunctionInCocosThread( std::bind(&HandWriteScene::resetHandWrite, this) );

                cmd.append("清除");
            }
            if(oneCmd.actDetail == PenStatus_BLUE){
                penColor = Color4F::BLUE;
                cmd.append("蓝");
            }
            if(oneCmd.actDetail == PenStatus_BLACK){
                penColor = Color4F::WHITE;
                cmd.append("黑");
            }
            if(oneCmd.actDetail == PenStatus_RED){
                penColor = Color4F::RED;
                cmd.append("红");
            }
            if(oneCmd.actDetail == PenStatus_PEN_FINE){
                lineWidth-=4;
                if(lineWidth<4){
                    lineWidth = 4;
                }

                Director::getInstance()->getScheduler()->performFunctionInCocosThread( std::bind(&HandWriteScene::initDrawThing, this) );

                cmd.append("细笔");
            }
            if(oneCmd.actDetail == PenStatus_PEN_MEDIUM){
                lineWidth = 4;
                cmd.append("中笔");
            }
            if(oneCmd.actDetail == PenStatus_PEN_BOLD){
                lineWidth+=1;
                if(lineWidth>40){
                    lineWidth = 40;
                }

                Director::getInstance()->getScheduler()->performFunctionInCocosThread( std::bind(&HandWriteScene::initDrawThing, this) );

                cmd.append("粗笔");
            }
            if(oneCmd.actDetail == PenStatus_MOUSE_CHOOSE){
                cmd.append("选鼠");
            }
            if(oneCmd.actDetail == PenStatus_PEN_CHOOSE){
                cmd.append("选笔");
            }
            if(oneCmd.actDetail == PenStatus_NEXT){
                cmd.append("下一页");
            }
            if(oneCmd.actDetail == PenStatus_PREV){
                cmd.append("上一页");
            }
        }

        //setNotifyLabel(cmd);
    }


    // implement the "static create()" method manually
    CREATE_FUNC(HandWriteScene);
private:
    cocos2d::Label*  displayLabel;
    cocos2d::Sprite* penHover;
    cocos2d::MotionStreak* penHoverMS;

    cocos2d::Size visibleSize;
    cocos2d::DrawNode* handNode;
    cocos2d::DrawNode* testHandNode;

    cocos2d::ParticleSystemQuad* _emitter;

    unsigned int lineWidth;
    float lastX;
    float lastY;

    float lastLastX;
    float lastLastY;

    float curX;
    float curY;

    Color4F penColor;
    float volumn;
    void initBg() {
        Vec2 origin = Director::getInstance()->getVisibleOrigin();

        //贴图的纹理图片宽高必须是2的n次幂，128x128
        auto bg = Sprite::create("blackboard.jpg",Rect(0, 0, visibleSize.width, visibleSize.height));

        //贴图的纹理参数，水平重复平铺，垂直重复平铺
        Texture2D::TexParams tp = {        backend::SamplerFilter::LINEAR,
                                           backend::SamplerFilter::LINEAR,
                                           backend::SamplerAddressMode::REPEAT,
                                           backend::SamplerAddressMode::REPEAT
        };
        bg->getTexture()->setTexParameters(tp);
        bg->setPosition(origin + Vec2(visibleSize.width/2, visibleSize.height/2));
        this->addChild(bg, -1);

    }
};

#endif //PROJ_ANDROID_HANDWRITESCENE_H